"use strict";
/** 
 * webpack打包时的配置项
*/
const path       = require("path");
const webpack    = require("webpack");
const merge      = require("webpack-merge");
const utils      = require("./utils");
const config     = require("./config");
const baseConfig = require("./base");


// 插件 - 分解任务和多线程管理
const HappyPack         = require("happypack");
// 插件 - 主要是为了抽离css样式,防止将样式打包在js中引起页面样式加载错乱的现象
const ExtractTextPlugin = require("extract-text-webpack-plugin");
// 插件 - 此插件使用uglify-js进行js文件的压缩
const UglifyJsPlugin    = require("uglifyjs-webpack-plugin");

// 插件 - 获取当前可用的port
const portfinder = require("portfinder");
// 插件 - webpack中拷贝文件和文件夹
const CopyWebpackPlugin    = require("copy-webpack-plugin");
// 插件 - 使用html-webpack-plugin插件
const HtmlWebpackPlugin    = require("html-webpack-plugin");
// 插件 - 识别某些类别的webpack错误，处理清理，聚合和优先级，以提供更好的开发人员体验
const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin");


// 配置项 - 创建进程池，分步运算文件
const HappyThreadPool = HappyPack.ThreadPool({size:5});

// 生产模式下 webpack的主要配置
const produceConfig = merge(baseConfig,{
    // 模块
    module: {
        rules: utils.styleLoaders({
            sourceMap: config.dev.cssSourceMap,
            extract: true,              // 提取样式到文件中
            usePostCSS: true            // 是否使用PostCSS插件
        })
    },
    // Source Map等
    devtool: config.build.devtool,
    // 输出
    output: {
        path: config.build.assetsRoot,
        filename: utils.assetsPath("js/[name].js"),     // .[chunkhash]
        chunkFilename: utils.assetsPath("js/[id].js")   // .[chunkhash]
    },
    plugins: [
        new HappyPack({
            id: "babel",
            loaders: ["babel-loader?cacheDirectory"],
            threadPool: HappyThreadPool
        }),
        // 使用uglify-js进行js文件的压缩: https://blog.csdn.net/u013884068/article/details/83511343
        new UglifyJsPlugin({
            uglifyOptions: {
                compress: {
                    // webpack删除没有用到的代码时不输出警告
                    warnings: false,
                    // 是否删除所有console.log语句
                    drop_console: true
                }
            },
            sourceMap: config.build.productionSourceMap,
            parallel: true                                  // 使用多进程并行运行来提高构建速度
        }),
        // 将CSS提取到文件中
        new ExtractTextPlugin({
            filename: utils.assetsPath("css/[name].css"),   //.[contenthash]
            allChunks: true
        }),
        // 压缩、去重提取css
        new OptimizeCSSPlugin({
            cssProcessorOptions: config.build.productionSourceMap
                ? { safe: true, map: { inline: false } }
                : { safe: true }
        }),
        // see： https://github.com/ampedandwired/html-webpack-plugin
        new HtmlWebpackPlugin({
            filename: config.build.index,
            template: resolve("clientSrc/index.html"),
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // type: 'none' | 'auto' | 'dependency' | 'manual' | {Function}
            chunksSortMode: "dependency"
        }),
        // 根据模块的相对路径生成一个四位数的hash作为模块id: https://webpack.docschina.org/plugins/hashed-module-ids-plugin/
        new webpack.HashedModuleIdsPlugin(),
        // 作用域提升(scope hoisting), 预编译所有模块到一个闭包中。
        new webpack.optimize.ModuleConcatenationPlugin(),
        // 用于建立一个独立文件(又称作 chunk)的功能：https://webpack.docschina.org/plugins/commons-chunk-plugin/ （webpack4中已经用SplitChunksPlugin替换）
        new webpack.optimize.CommonsChunkPlugin({
            name: "vendor",
            minChunks(module) {
                // any required modules inside node_modules are extracted to vendor
                // module.resource: 文件名 module.context: 文件目录
                // 满足条件时移动库到独立文件（chunk）中
                return (
                    module.resource &&
                    /\.js|\.ts|\.tsx$/.test(module.resource) &&
                    module.resource.indexOf(
                        resolve("node_modules")
                    ) === 0
                );
            }
        }),
        // 创建模块清单
        new webpack.optimize.CommonsChunkPlugin({
            name: "manifest",
            // Infinity: 创建一个公共模块，但其中不会存在任何模块依赖
            minChunks: Infinity
        }),
        // 创建它是为了新的异步加载的额外公共chunk。
        new webpack.optimize.CommonsChunkPlugin({
            name: "app",
            async: "vendor-async",  // 创建一个异步 公共chunk
            children: true,         // 选择所有被选 chunks 的子 chunks
            minChunks: 3            // 在提取之前需要至少三个子 chunk 共享这个模块
        }),
        new CopyWebpackPlugin([{
            from: resolve("public"),
            to: config.build.assetsSubDirectory,
            ignore: [".*"]
        }])
    ]
});

module.exports = produceConfig;


// 路径获取的封装
function resolve(dir) {
    return path.join(__dirname, "..", dir);
};